import {
  Injectable,
  OnModuleInit,
  OnModuleDestroy,
  Logger,
} from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService
  extends PrismaClient
  implements OnModuleInit, OnModuleDestroy
{
  private readonly logger = new Logger(PrismaService.name);
  private isConnected = false;
  private readonly MAX_RETRIES = parseInt(
    process.env.DB_MAX_RETRIES || '3',
    10,
  );
  private readonly RETRY_DELAY = parseInt(
    process.env.DB_RETRY_DELAY || '1000',
    10,
  );

  constructor() {
    super({
      log: ['error', 'warn'],
      errorFormat: 'minimal', // Reduces the verbosity of error messages
    });
  }

  async isHealthy(): Promise<boolean> {
    try {
      await this.$queryRaw`SELECT 1`;
      return true;
    } catch (err) {
      this.logger.error('Database health check failed', err);
      return false;
    }
  }

  async onModuleInit() {
    let retries = 0;
    while (retries < this.MAX_RETRIES) {
      try {
        await this.$connect();
        this.isConnected = true;
        this.logger.log('Successfully connected to database');
        return;
      } catch (err) {
        retries++;
        this.logger.error(
          `Database connection failed (attempt ${retries}/${this.MAX_RETRIES})`,
          err instanceof Error ? err.message : 'Unknown error',
        );
        if (retries === this.MAX_RETRIES) {
          throw new Error(
            'Failed to connect to database after maximum retries',
          );
        }
        await new Promise((resolve) => setTimeout(resolve, this.RETRY_DELAY));
      }
    }
  }

  async onModuleDestroy() {
    try {
      await this.$disconnect();
      this.isConnected = false;
      this.logger.log('Successfully disconnected from database');
    } catch (err) {
      this.logger.error(
        'Error disconnecting from database',
        err instanceof Error ? err.message : 'Unknown error',
      );
      throw err;
    }
  }
}
